package com.example.mvvm.base;

import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Message;

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.Observer;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.OnLifecycleEvent;

import com.example.mvvm.base.livedata.MessageLiveEvent;
import com.example.mvvm.base.livedata.SingleLiveEvent;
import com.example.mvvm.base.livedata.StatusLiveEvent;
import com.example.mvvm.http.HttpClient;
import com.example.mvvm.http.RetrofitApi;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class BaseViewModel extends AndroidViewModel implements LifecycleObserver, Consumer<Disposable> {
    // 订阅管理器
    private CompositeDisposable mDisposable;

    /**
     * 消息事件
     */
    private MessageLiveEvent messageEvent = new MessageLiveEvent();
    /**
     * 状态事件
     */
    private StatusLiveEvent statusEvent = new StatusLiveEvent();

    /**
     * 加载状态
     */
    private SingleLiveEvent<Boolean> loadingEvent = new SingleLiveEvent<>();

    /**
     * 提供自定义单一消息事件
     */
    private SingleLiveEvent<Message> singleEvent = new SingleLiveEvent<>();


    public BaseViewModel(@NonNull Application application) {
        super(application);
        mDisposable = new CompositeDisposable();
    }

    @Override
    public void accept(Disposable disposable) throws Throwable {
        // 添加订阅
        addDisposable(disposable);
    }


    /**
     * 统一管理订阅消息
     *
     * @param disposable 实例对象
     */
    protected void addDisposable(Disposable disposable) {
        if (mDisposable == null) {
            mDisposable = new CompositeDisposable();
        }
        mDisposable.add(disposable);
    }

    @Override
    protected void onCleared() {
        if (mDisposable != null) {
            mDisposable.dispose();
            mDisposable.clear();
        }
        super.onCleared();
    }

    protected <T> Observable<T> network(Observable<T> observable) {
        return observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }


    public RetrofitApi api() {
        return HttpClient.getApi();
    }


    protected void isDisposed() {
        mDisposable.isDisposed();
    }


    /**
     *  暴露给观察者提供加载事件，{@link BaseActivity} 或 {@link BaseFragment} 已默认注册加载事件，
     *  只需调用{@link #showLoading()} 或 {@link #hideLoading()}即可在{@link BaseActivity}
     *  或 {@link BaseFragment} 中收到订阅事件
     * @return {@link #loadingEvent}
     */
    public SingleLiveEvent<Boolean> getLoadingEvent(){
        return loadingEvent;
    }

    /**
     * 暴露给观察者提供消息事件，通过注册{@link BaseActivity#registerMessageEvent(MessageLiveEvent.MessageObserver)}或
     * {@link BaseFragment#registerMessageEvent(MessageLiveEvent.MessageObserver)} 或
     * @return {@link #messageEvent}
     */
    public MessageLiveEvent getMessageEvent(){
        return messageEvent;
    }

    /**
     * 暴露给观察者提供状态变化事件，通过注册{@link BaseActivity#registerStatusEvent(StatusLiveEvent.StatusObserver)}或
     * {@link BaseFragment#registerStatusEvent(StatusLiveEvent.StatusObserver)} 或
     * @return {@link #statusEvent}
     */
    public StatusLiveEvent getStatusEvent(){
        return statusEvent;
    }

    /**
     * 暴露给观察者提供接收单个消息事件，通过注册{@link BaseActivity#registerSingleLiveEvent(Observer)}或
     * {@link BaseFragment#registerSingleLiveEvent(Observer)} 或
     * @return {@link #singleEvent}
     */
    public SingleLiveEvent<Message> getSingleLiveEvent(){
        return singleEvent;
    }

    /**
     * 发送消息，通过注册{@link BaseActivity#registerMessageEvent(MessageLiveEvent.MessageObserver)}或
     * {@link BaseFragment#registerMessageEvent(MessageLiveEvent.MessageObserver)} 或
     * 也可通过观察{@link #getMessageEvent()}接收消息事件
     * @param msgId 资源文件id
     */
    @MainThread
    public void sendMessage(@StringRes int msgId) {
        sendMessage(msgId,false);
    }

    /**
     * 发送消息，通过注册{@link BaseActivity#registerMessageEvent(MessageLiveEvent.MessageObserver)}或
     * {@link BaseFragment#registerMessageEvent(MessageLiveEvent.MessageObserver)} 或
     * 也可通过观察{@link #getMessageEvent()}接收消息事件
     * @param msgId 资源文件id
     * @param post 如果为{@code true}则可以在子线程调用，相当于调用{@link MutableLiveData#postValue(Object)}，
     *             如果为{@code false} 相当于调用{@link MutableLiveData#setValue(Object)}
     */
    public void sendMessage(@StringRes int msgId, boolean post) {
        sendMessage(getApplication().getString(msgId),post);
    }

    /**
     * 发送消息，通过注册{@link BaseActivity#registerMessageEvent(MessageLiveEvent.MessageObserver)}或
     * {@link BaseFragment#registerMessageEvent(MessageLiveEvent.MessageObserver)} 或
     * 也可通过观察{@link #getMessageEvent()}接收消息事件
     * @param message 消息内容
     */
    @MainThread
    public void sendMessage(String message){
        messageEvent.setValue(message);
    }

    /**
     * 发送消息，通过注册{@link BaseActivity#registerMessageEvent(MessageLiveEvent.MessageObserver)}或
     * {@link BaseFragment#registerMessageEvent(MessageLiveEvent.MessageObserver)} 或
     * 也可通过观察{@link #getMessageEvent()}接收消息事件
     * @param message 消息内容
     * @param post 如果为{@code true}则可以在子线程调用，相当于调用{@link MutableLiveData#postValue(Object)}，
     *             如果为{@code false} 相当于调用{@link MutableLiveData#setValue(Object)}
     */
    public void sendMessage(String message,boolean post){
        if(post){
            messageEvent.postValue(message);
        }else{
            messageEvent.setValue(message);
        }
    }


    /**
     * 更新状态，通过注册{@link BaseActivity#registerStatusEvent(StatusLiveEvent.StatusObserver)}或
     * {@link BaseFragment#registerStatusEvent(StatusLiveEvent.StatusObserver)} 或
     * 也可通过观察{@link #getStatusEvent()}接收消息事件
     * @param status
     */
    @MainThread
    public void updateStatus(@StatusLiveEvent.Status int status){
        updateStatus(status,false);
    }

    /**
     * 更新状态，通过注册{@link BaseActivity#registerStatusEvent(StatusLiveEvent.StatusObserver)}或
     * {@link BaseFragment#registerStatusEvent(StatusLiveEvent.StatusObserver)} 或
     * 也可通过观察{@link #getStatusEvent()}接收消息事件
     * @param status
     * @param post 如果为{@code true}则可以在子线程调用，相当于调用{@link MutableLiveData#postValue(Object)}，
     *             如果为{@code false} 相当于调用{@link MutableLiveData#setValue(Object)}
     */
    public void updateStatus(@StatusLiveEvent.Status int status, boolean post){
        if(post){
            statusEvent.postValue(status);
        }else{
            statusEvent.setValue(status);
        }
    }

    /**
     * 发送单个消息事件，消息为{@link Message}对象，可通过{@link Message#what}区分消息类型，用法与{@link Message}一致，
     * 通过注册{@link BaseActivity#registerSingleLiveEvent(Observer)}或
     * {@link BaseFragment#registerSingleLiveEvent(Observer)} 或
     * 也可通过观察{@link #getSingleLiveEvent()}接收消息事件
     * @param what
     */
    @MainThread
    public void sendSingleLiveEvent(int what){
        sendSingleLiveEvent(what,false);
    }

    /**
     * 发送单个消息事件，消息为{@link Message}对象，可通过{@link Message#what}区分消息类型，用法与{@link Message}一致，
     * 通过注册{@link BaseActivity#registerSingleLiveEvent(Observer)}或
     * {@link BaseFragment#registerSingleLiveEvent(Observer)} 或
     * 也可通过观察{@link #getSingleLiveEvent()}接收消息事件
     * @param what
     * @param post 如果为{@code true}则可以在子线程调用，相当于调用{@link MutableLiveData#postValue(Object)}，
     *             如果为{@code false} 相当于调用{@link MutableLiveData#setValue(Object)}
     */
    public void sendSingleLiveEvent(int what, boolean post){
        Message message = Message.obtain();
        message.what = what;
        sendSingleLiveEvent(message,post);
    }

    /**
     * 发送单个消息事件，消息为{@link Message}对象，可通过{@link Message#what}区分消息类型，用法与{@link Message}一致，
     * 通过注册{@link BaseActivity#registerSingleLiveEvent(Observer)}或
     * {@link BaseFragment#registerSingleLiveEvent(Observer)} 或
     * 也可通过观察{@link #getSingleLiveEvent()}接收消息事件
     * @param message
     */
    @MainThread
    public void sendSingleLiveEvent(Message message){
        sendSingleLiveEvent(message,false);
    }

    /**
     * 发送单个消息事件，消息为{@link Message}对象，可通过{@link Message#what}区分消息类型，用法与{@link Message}一致，
     * 通过注册{@link BaseActivity#registerSingleLiveEvent(Observer)}或
     * {@link BaseFragment#registerSingleLiveEvent(Observer)} 或
     * 也可通过观察{@link #getSingleLiveEvent()}接收消息事件
     * @param message
     * @param post 如果为{@code true}则可以在子线程调用，相当于调用{@link MutableLiveData#postValue(Object)}，
     *             如果为{@code false} 相当于调用{@link MutableLiveData#setValue(Object)}
     */
    public void sendSingleLiveEvent(Message message, boolean post){
        if(post){
            singleEvent.postValue(message);
        }else{
            singleEvent.setValue(message);
        }
    }

    /**
     * 调用此类会同步通知执行{@link BaseActivity#showLoading()}或{@link BaseFragment#showLoading()}或
     */
    @MainThread
    public void showLoading() {
        showLoading(false);
    }

    /**
     * 调用此类会同步通知执行{@link BaseActivity#showLoading()}或{@link BaseFragment#showLoading()}或
     */
    public void showLoading(boolean post) {
        if(post){
            loadingEvent.postValue(true);
        }else{
            loadingEvent.setValue(true);
        }
    }

    /**
     * 调用此类会同步通知执行{@link BaseActivity#hideLoading()}或{@link BaseFragment#hideLoading()}或
     */
    @MainThread
    public void hideLoading() {
        hideLoading(false);
    }


    /**
     * 调用此类会同步通知执行{@link BaseActivity#hideLoading()}或{@link BaseFragment#hideLoading()}或
     * @param post 如果为{@code true}则可以在子线程调用，相当于调用{@link MutableLiveData#postValue(Object)}，
     *             如果为{@code false} 相当于调用{@link MutableLiveData#setValue(Object)}
     */
    public void hideLoading(boolean post) {
        if(post){
            loadingEvent.postValue(false);
        }else{
            loadingEvent.setValue(false);
        }
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void onCreate() {
    }


    /**
     * 跳转页面
     *
     * @param cls target Activity
     */
    protected void startActivity(@NonNull Context context, @NonNull Class<?> cls) {
        Intent intent = new Intent(context, cls);
        context.startActivity(intent);
    }

}
